package retrieval;

import org.xml.sax.*;
import org.xml.sax.helpers.*;
import java.util.*;

import org.dom4j.Document;

public class QueryOnDAGBKI extends DefaultHandler
{
    public ArrayList<String>            nodeList      = new ArrayList<String>();
    public Stack<String>                nodeStack     = new Stack<String>();
    public Hashtable<String, Node>      nodeInfo      = new Hashtable<String, Node>();
    public ArrayList<ArrayList<String>> tree          = new ArrayList<ArrayList<String>>();
    public XRetrievalTreeGenerator      treeGenerator = new XRetrievalTreeGenerator();
    public String                       xmlName       = "";

    public QueryOnDAGBKI(String str)
    {
        xmlName = str;
    }

    public void startElement(String uri, String localName, String qName,
            Attributes attributes)
    {
        try
        {
            nodeList.add(qName);
            Node node = new Node();
            node.nodeName = qName;
            nodeInfo.put(qName, node);
            nodeStack.push(qName);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void characters(char[] ch, int start, int length)
    {
        String text = new String(ch, start, length);
        String currentKeyword;
        String currentNode = nodeStack.peek().toString();
        // System.out.print("*****Node:" + currentNode + ";   text:" + text
        // + ";  length:" + Integer.toString(length) + ";$$$$$$$$");
        // System.out.println();
        try
        {
            if (length > 1)
            {
                Iterator<String> it1 = CreateDAGBKI.keywordSet.iterator();
                while (it1.hasNext())
                {
                    currentKeyword = (String) it1.next().toString();
                    if (text.contains(currentKeyword))
                    {
                        if (!nodeInfo.get(currentNode).keywordList
                                .contains(currentKeyword))
                        {
                            nodeInfo.get(currentNode).keywordList
                                    .add(currentKeyword);
                            nodeInfo.get(currentNode).keyword2ancestor.put(
                                    currentKeyword, new HashSet<String>());
                            nodeInfo.get(currentNode).directIncluding
                                    .add(currentKeyword);
                            Iterator<String> it2 = CreateDAGBKI.keyword2query
                                    .get(currentKeyword).iterator();
                            while (it2.hasNext())
                            {
                                String tmp = ((String) it2.next()).toString();
                                if (!nodeInfo.get(currentNode).relatedQueryList
                                        .contains(tmp))
                                    nodeInfo.get(currentNode).relatedQueryList
                                            .add(tmp);
                            }
                        }
                    }
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

    }

    public void endElement(String uri, String localName, String qName)
    {
        String currentNode = nodeStack.pop().toString();
        String nextNode = "";
        if (!nodeStack.empty())
        {
            nextNode = nodeStack.peek().toString();
        }
        try
        {
            processRelatedQuery(nodeInfo.get(currentNode).relatedQueryList,
                    currentNode);
            if (!nodeStack.empty())
            {
                Iterator<String> it1 = nodeInfo.get(currentNode).relatedQueryList
                        .iterator();
                while (it1.hasNext())
                {
                    nodeInfo.get(nextNode).relatedQueryList.add((String) it1
                            .next());
                }
                Iterator<String> it2 = nodeInfo.get(currentNode).keywordList
                        .iterator();
                while (it2.hasNext())
                {
                    String tmp = (String) it2.next().toString();
                    nodeInfo.get(nextNode).keywordList.add(tmp);
                    if (nodeInfo.get(nextNode).keyword2ancestor
                            .containsKey(tmp))
                    {
                        nodeInfo.get(nextNode).keyword2ancestor.get(tmp).add(
                                currentNode);
                    }
                    else
                    {
                        nodeInfo.get(nextNode).keyword2ancestor.put(tmp,
                                new HashSet<String>());
                        nodeInfo.get(nextNode).keyword2ancestor.get(tmp).add(
                                currentNode);
                    }
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void endDocument()
    {
        try
        {
            Set<String> set1 = CreateDAGBKI.uselessNodeList.keySet();
            for (String str : set1)
            {
                CreateDAGBKI.uselessNodeList.put(str, new HashSet<String>());
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void processRelatedQuery(HashSet<String> set, String str)
    {
        String currentNode = str;
        tree = new ArrayList<ArrayList<String>>();
        try
        {
            Iterator<String> it = set.iterator();
            while (it.hasNext())
            {
                String tmp = ((String) it.next()).toString();
                if (CreateDAGBKI.uselessNodeList.get(tmp).contains(currentNode))
                    continue;
                if (nodeInfo.get(currentNode).keywordList
                        .containsAll(CreateDAGBKI.queryList.get(tmp).keywords))
                {
                    outputSRCT(currentNode, tmp);
                    // this.display(tree, tmp);
                    // test.generate(tree);

                    // treeGenerator.display(treeGenerator.generate(tree));
                    Document doc = treeGenerator.generate(tree);
                    if (CreateDAGBKI.queryResult.containsKey(tmp))
                    {
                        if (CreateDAGBKI.queryResult.get(tmp).containsKey(
                                xmlName))
                        {
                            CreateDAGBKI.queryResult.get(tmp).get(xmlName).add(
                                    doc);
                        }
                        else
                        {
                            CreateDAGBKI.queryResult.get(tmp).put(xmlName,
                                    new HashSet<Document>());
                            CreateDAGBKI.queryResult.get(tmp).get(xmlName).add(
                                    doc);
                        }
                    }
                    else
                    {
                        CreateDAGBKI.queryResult.put(tmp,
                                new Hashtable<String, HashSet<Document>>());
                        if (CreateDAGBKI.queryResult.get(tmp).containsKey(
                                xmlName))
                        {
                            CreateDAGBKI.queryResult.get(tmp).get(xmlName).add(
                                    doc);
                        }
                        else
                        {
                            CreateDAGBKI.queryResult.get(tmp).put(xmlName,
                                    new HashSet<Document>());
                            CreateDAGBKI.queryResult.get(tmp).get(xmlName).add(
                                    doc);
                        }
                    }
                    CreateDAGBKI.uselessNodeList.get(tmp).add(currentNode);
                    Iterator<String> st = nodeStack.iterator();
                    while (st.hasNext())
                    {
                        String element = ((String) st.next()).toString();
                        nodeInfo.get(element).relatedQueryList.remove(tmp);
                        CreateDAGBKI.uselessNodeList.get(tmp).add(element);
                    }
                    processRelatedQuery(CreateDAGBKI.query2parents.get(tmp),
                            currentNode);
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void outputSRCT(String root, String queryName)
    {
        String currentNode = root;
        try
        {
            HashSet<String> set = CreateDAGBKI.queryList.get(queryName).keywords;
            for (Iterator<String> it = set.iterator(); it.hasNext();)
            {
                String currentKeyword = (String) it.next();
                ArrayList<String> subTree = new ArrayList<String>();
                recursionArrayList(currentNode, currentKeyword, subTree);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void recursionArrayList(String currentNode, String currentKeyword,
            ArrayList<String> subTree)
    {
        subTree.add(currentNode);
        if (nodeInfo.get(currentNode).directIncluding.contains(currentKeyword))
        {
            subTree.add(currentKeyword);
            ArrayList<String> tmp = new ArrayList<String>();
            for (String str : subTree)
            {
                tmp.add(str);
            }
            tree.add(tmp);
            subTree.remove(currentKeyword);
        }
        for (Iterator<String> it = nodeInfo.get(currentNode).keyword2ancestor
                .get(currentKeyword).iterator(); it.hasNext();)
        {
            String nextNode = (String) it.next();
            recursionArrayList(nextNode, currentKeyword, subTree);
        }
        subTree.remove(currentNode);
    }

    public void display(ArrayList<ArrayList<String>> tree, String query)
    {
        System.out.println("************Tree for" + query + ":*************");
        for (ArrayList<String> subTree : tree)
        {
            for (String node : subTree)
            {
                System.out.print(node + "---");
            }
            System.out.println();
        }
        System.out.println();
    }
}
